package org.tech4j.edi.common.result;

import org.apache.commons.lang3.StringUtils;
import org.tech4j.common.core.enums.ErrorCode;
import org.tech4j.common.core.model.result.IResult;

import java.io.Serial;
import java.io.Serializable;

/**
 * @program: tech4j
 * @description:
 * @author: YuKai Fan
 * @create: 2025/3/7 10:44
 **/
public class EdiResult<T> implements IResult, Serializable {

    @Serial
    private static final long serialVersionUID = -1644831525449537579L;
    private Integer code;

    private String message;

    private Boolean success;

    private T data;

    @Override
    public Integer getCode() {
        return code;
    }

    @Override
    public void setCode(Integer code) {
        this.code = code;
    }

    @Override
    public String getMessage() {
        return message;
    }

    @Override
    public void setMessage(String message) {
        this.message = message;
    }

    @Override
    public Boolean getSuccess() {
        return success;
    }

    @Override
    public void setSuccess(Boolean success) {
        this.success = success;
    }

    public T getData() {
        return data;
    }

    public void setData(T data) {
        this.data = data;
    }

    public static EdiResult<Void> ofSuccess() {
        return ofSuccess(null);
    }

    public static <T> EdiResult<T> ofSuccess(T data) {
        return ofSuccess(SUCCESS_CODE, SUCCESS_MESSAGE, data);
    }

    public static EdiResult<Void> ofSuccess(int code, String message) {
        return ofSuccess(code, message, null);
    }

    public static <T> EdiResult<T> ofSuccess(int code, String message, T data) {
        return Builder.<T>builder()
                .code(code)
                .message(message)
                .data(data)
                .success(true)
                .build();
    }

    public static EdiResult<Void> ofFailed(int code, String message) {
        return Builder.<Void>builder()
                .code(code)
                .message(message)
                .success(false)
                .build();
    }

    public static EdiResult<Void> ofFailed(ErrorCode errorCode) {
        return Builder.<Void>builder()
                .code(errorCode.getCode())
                .message(errorCode.getMessage())
                .success(false)
                .build();
    }

    public static <T> EdiResult<T> ofFailed0(ErrorCode errorCode) {
        return Builder.<T>builder()
                .code(errorCode.getCode())
                .message(errorCode.getMessage())
                .success(false)
                .build();
    }

    public static <T> EdiResult<T> ofFailed0(ErrorCode errorCode, String... args) {
        String errorMsg = String.format(errorCode.getMessage(), args);
        // 说明StringFormat不启作用
        if (StringUtils.equals(errorMsg, errorCode.getMessage())) {
            StringBuffer sb = new StringBuffer();
            sb.append(errorCode.getMessage()).append("，详情：");
            if (args != null) {
                for (String arg : args) {
                    sb.append(arg).append(" ");
                }
            }
            errorMsg = sb.toString();
        }
        return Builder.<T>builder()
                .code(errorCode.getCode())
                .message(errorMsg)
                .success(false)
                .build();
    }

    public static <T> EdiResult<T> ofFailed0(int code, String message) {
        return Builder.<T>builder()
                .code(code)
                .message(message)
                .success(false)
                .build();
    }

    public boolean isFailed() {
        return !success;
    }


    public static final class Builder<T> {
        private T data;
        private Boolean success;
        private String message;
        private Integer code;

        private Builder() {
        }

        public static <T> Builder<T> builder() {
            return new Builder<>();
        }

        public Builder<T> data(T data) {
            this.data = data;
            return this;
        }

        public Builder<T> success(Boolean success) {
            this.success = success;
            return this;
        }

        public Builder<T> message(String message) {
            this.message = message;
            return this;
        }

        public Builder<T> code(Integer code) {
            this.code = code;
            return this;
        }

        public EdiResult<T> build() {
            EdiResult<T> ediResult = new EdiResult<>();
            ediResult.setData(data);
            ediResult.setSuccess(success);
            ediResult.setMessage(message);
            ediResult.setCode(code);
            return ediResult;
        }
    }
}
